//
// Created by mio on 25-4-14.
//

#include "TcpServer.h"

#include <Acceptor.h>
#include <EventLoop.h>

TcpServer::TcpServer(EventLoop* eventloop) :
    loop_(eventloop), port_(0), acceptor_(std::make_unique<Acceptor>(eventloop))
{
    acceptor_->SetNewConnectionCallback([this](int fd)
    {
       TcpConnectionPtr conn = this->OnConnect(fd);
        if (conn)
        {
            this->AddConnection(fd, conn);
            conn->SetDisConnectCallback([this](TcpConnectionPtr conn)
            {
                int fd = conn->GetSocket();
                this->RemoveConnection(fd);
            });
            conn->SetCloseCallback([this](TcpConnectionPtr conn)
            {
                int fd = conn->GetSocket();
                this->RemoveConnection(fd);
            });
        }
    });
}


TcpServer::~TcpServer()
{
    Stop();
}

bool TcpServer::Start(std::string ip, uint16_t port)
{
    Stop();
    if (!is_started_)
    {
        if (acceptor_->Listen(ip, port) < 0) return false;
        port_ = port;
        ip_ = ip;
        is_started_ = true;
    }
    return true;
}

void TcpServer::Stop()
{
    if (is_started_)
    {
        for (auto it : connections_)
        {
            it.second->DisConnect();
        }
        acceptor_->Close();
        is_started_ = false;
    }
}

TcpConnectionPtr TcpServer::OnConnect(int fd)
{
    return std::make_shared<TcpConnection>(loop_->GetTaskScheduler().get(), fd);
}

void TcpServer::AddConnection(int fd, TcpConnectionPtr conn)
{
    std::lock_guard<std::mutex> lock(mtx_);
    connections_.emplace(fd, conn);
}

void TcpServer::RemoveConnection(int fd)
{
    std::lock_guard<std::mutex> lock(mtx_);
    connections_.erase(fd);
}
